import time
# from logging import exception
from selenium import webdriver
# from selenium.webdriver.common.by import By
# from selenium.webdriver.support.ui import WebDriverWait
# from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
import os, random, traceback


# from logging import exception
# from selenium import webdriver
# from selenium.webdriver.common.by import By
# from selenium.webdriver.support.ui import WebDriverWait
# from selenium.webdriver.support import expected_conditions as EC
def aligns(string, length):
    difference = length - len(string)  # 计算限定长度为20时需要补齐多少个空格
    if difference == 0:  # 若差值为0则不需要补
        return string
    elif difference < 0:
        print('错误：限定的对齐长度小于字符串长度!')
        return None
    new_string = ''
    space = '　'
    for i in string:
        codes = ord(i)  # 将字符转为ASCII或UNICODE编码
        if codes <= 126:  # 若是半角字符
            new_string = new_string + chr(codes + 65248)  # 则转为全角
        else:
            new_string = new_string + i  # 若是全角，则不转换
    return new_string + space * (difference)  # 返回补齐空格后的字符串


def my_align(string, length, align_type='<'):
    """
    :param string: 中英文混排时待列对齐的原字符串
    :param length: 待预留列宽,折合的半角字符总数,默认0
    :param align_type: 对齐类型,默认左对齐.左对齐<,右对齐>,居中对齐-
    :return: 补充空格后的字符串
    """
    if length <= len(string.encode('GBK')):
        return string
    len_ch = (len(string.encode('GBK')) - len(string)) * 2  # 中文折合的半角字符总数
    len_en = len(string) * 2 - len(string.encode('GBK'))  # 英文折合的半角字符总数
    len_sp = length - len_ch - len_en  # 补充空格总数
    if align_type == '>':  # 右对齐
        return ' ' * len_sp + string
    elif align_type == '-':  # 居中对齐
        return ' ' * int(len_sp / 2) + string + ' ' * (len_sp - int(len_sp / 2))
    return string + ' ' * len_sp  # 左对齐


class zjy2():

    def __init__(self):  # 初始化
        # 创建 WebDriver 对象，指明使用chrome浏览器驱动
        option = webdriver.ChromeOptions()
        # 防止打印一些无用的日志
        option.add_experimental_option("excludeSwitches", ['enable-automation', 'enable-logging'])
        # 静音
        option.add_argument("--mute-audio")
        # 定义浏览器浏览器的路径到本地
        option.binary_location = "./chrome.exe"
        # 跑起来
        if(os.path.isfile(r'.\chromedriver.exe')==False):
            print("未找到 Google chromedriver 请将chromedriver放在与本程序同目录下")
            quit()
        self.wd = webdriver.Chrome(r'.\chromedriver.exe', options=option)
        # 设置最大等待时长为 10秒
        self.wd.implicitly_wait(1)

        self.login_start = False  # 登录状态
        self.kecheng_list = []  # 课程列表
        self.class_list = []  # 课程

    def login_sd(self):  # 手动账号密码登录
        self.wd.get('https://zjy2.icve.com.cn/portal/login.html')
        print("请等待登录提示！>")
        while True:
            if (self.wd.find_element_by_id("btnLogin").text == "登录"):
                break

        while True:
            print("页面加载完成,请在浏览器中登录您的帐号:")
            num = input("并且登录成功后在本窗口下按下回车>")
            try:
                element = self.wd.find_elements_by_class_name("leftSiderbar")
                if (element[5].text == "首页"):
                    print("登录成功", self.wd.find_element_by_class_name("np-info").text)
                    self.login_start = True
                    break
                else:
                    print("登录失败 请重试")
            except NoSuchElementException:
                print("未检测到成功登陆,请重试！")
            except Exception:
                print("未检测到成功登陆,请重试！")

    def login_ck(self):  # cookies 登录
        self.wd.get('https://zjy2.icve.com.cn/portal/login.html')
        print("请等待登录提示！>")
        while True:
            if (self.wd.find_element_by_id("btnLogin").text == "登录"):
                break
        while True:
            print("页面加载完成,请输入你成功登录状态下的cookies:")
            ck = input("输入后按下回车：")
            self.addcookies(ck)
            time.sleep(1)
            self.wd.get("https://zjy2.icve.com.cn/student/studio/studio.html")

            try:
                element = self.wd.find_elements_by_class_name("leftSiderbar")
                if (element[5].text == "首页"):
                    print("登录成功", self.wd.find_element_by_class_name("np-info").text)
                    self.login_start = True
                    break
                else:
                    self.wd.get('https://zjy2.icve.com.cn/portal/login.html')
                    print("登录失败 请重试")
            except NoSuchElementException:
                self.wd.get('https://zjy2.icve.com.cn/portal/login.html')
                print("未检测到成功登陆,请重试！")
            except Exception:
                self.wd.get('https://zjy2.icve.com.cn/portal/login.html')
                print("未检测到成功登陆,请重试！")

    def login_zjy2(self):  # 实际上是个登录菜单
        print("-" * 30)
        print("输入 0 使用账户密码手动登录\n输入 1 使用cookies登录")
        num = input("请输入你的选择:")
        print("-" * 30)
        if (num == "0"):
            self.login_sd()
        elif (num == "1"):
            self.login_ck()
        else:
            print("输入指令有误")

    def get_course_list(self):  # 取得课程列表
        self.wd.get("https://zjy2.icve.com.cn/student/studio/studio.html")
        while True:
            try:
                element = self.wd.find_elements_by_class_name("leftSiderbar")
                if (element[5].text == "首页"):
                    break
                else:
                    pass
            except NoSuchElementException:
                pass
            except Exception:
                pass
        self.kecheng_list = []  # 课程列表
        element_url = self.wd.find_elements_by_xpath("""//li[@class="kt-lesson-li"]/div/a""")
        element_text = self.wd.find_elements_by_xpath("""//li[@class="kt-lesson-li"]/div/div""")
        # print(len(element_text),len(element_url))

        for i in range(1, len(element_text)):
            line_list = element_text[i].text.split("\n"),
            # print(line_list)
            dist = {}
            dist["name"] = line_list[0][0].replace("（", "(").replace("）", ")")
            dist["year"] = line_list[0][1]
            dist["cols"] = line_list[0][2]
            dist["start"] = line_list[0][3]
            dist["teacher"] = line_list[0][4]
            dist["url"] = element_url[i - 1].get_attribute("href")
            self.kecheng_list.append(dist)
            # print(element_text[i].text.split("\n"),"\n----------------")
            # print(element_url[i-1].get_attribute("href"))

        # for line in self.kecheng_list:
        #     print(line)

    def show_course_list(self):  # 显示课程列表
        for i in range(len(self.kecheng_list)):
            # print(self.kecheng_list[i])
            # print("序号:{:5}\t课程名:{:40}\t状态:{:10}".format(str(i+1),self.kecheng_list[i]["name"],self.kecheng_list[i]["start"]))
            # print(aligns("序号:" + str(i + 1), 8) +  aligns("课程名:" + self.kecheng_list[i]["name"], 40)+aligns("状态:" + self.kecheng_list[i]["start"], 8))
            print(my_align("序号:" + str(i + 1), 10) + my_align("课程名:" + self.kecheng_list[i]["name"], 50) + my_align(
                "进度:" + self.kecheng_list[i]["cols"], 0))

    def addcookies(self, cookies):  # 添加cookies
        cookies = cookies.replace(" ", "")
        cookie = {}
        for lines in cookies.split(';'):
            line = lines.strip().split('=', 1)
            # print(line)
            if (len(line) == 2):
                cookie["name"] = line[0]
                cookie["value"] = line[1]
                self.wd.add_cookie(cookie)

    def open_class_tab(self):  # 展开课程菜单
        print("展开课程列表")
        # 疑似列表有缓存>
        element = ""
        element1 = ""
        element = self.wd.find_elements_by_xpath("""//div[@class="sh-toc-pd openOrCloseModule"]""")
        element1 = self.wd.find_elements_by_xpath("""//div[@class="sh-toc-pd openOrCloseModule"]/span""")
        # print(element, element1)
        # print("element", len(element))
        # print("element1", len(element1))
        i = 1  # 判断是否是展开状态 不是就展开列表
        j = 0
        time.sleep(3)
        for line in element:
            j = j + 1
            if (element1[i].get_attribute('class') == "am-icon sh-toc-expand module_condensation am-icon-caret-right"):
                # print(j)
                line.click()
                time.sleep(float("{:.1f}".format(random.uniform(0, 1))))
            else:
                pass
            i = i + 3

        time.sleep(3)
        element = self.wd.find_elements_by_class_name("openOrCloseTopic")
        for line in element:
            line.click()
            time.sleep(float("{:.1f}".format(random.uniform(0, 1))))

    def play_ysb(self):  # 加载压缩包
        print("play_ysb 已加载")

    def play_video(self):  # 播放视频
        print("play_video已加载")
        # 是否已加载播放页面
        element = self.wd.find_element_by_class_name("am-active.tabChange-li")
        while True:
            if (element.text == "评价"):
                break
        # 定位播放的位置
        video = self.wd.find_element_by_tag_name("video")
        # 定位播放按钮
        videobtn = self.wd.find_element_by_class_name("jw-icon.jw-icon-display.jw-button-color.jw-reset")
        print("video", video)

        while True:  # 有时候url会加载不出来或者慢
            url = self.wd.execute_script("return arguments[0].currentSrc;", video)
            print("url", url)
            if (url != ""):
                break
            time.sleep(3)

        videobtn.click()  # 激活播放
        video_stop_i = 0
        time.sleep(2)
        self.wd.execute_script("return arguments[0].play()", video)  # 播放
        while True:
            print("当前：{:.2f}/{:.2f}".format(self.wd.execute_script("return arguments[0].currentTime", video),
                                            self.wd.execute_script("return arguments[0].duration", video)))
            #
            # print("当前：{:.2f}/{:.2f}".format(wd.execute_script("return arguments[0].currentTime", video),
            # wd.execute_script("return arguments[0].duration", video)))
            if (self.wd.execute_script("return arguments[0].currentTime", video) >= self.wd.execute_script(
                    "return arguments[0].duration", video)):
                break
            if (int(self.wd.execute_script("return arguments[0].currentTime", video)) == 0):
                video_stop_i = video_stop_i + 1

            if (video_stop_i == 4):
                self.wd.refresh()
                self.play_video()
            elif (video_stop_i == 2):
                self.wd.execute_script("return arguments[0].play()", video)  # 播放

            time.sleep(60)
        time.sleep(1)

    def is_Kejian_butong(self):  # 检查是否有阅读不一致提示
        time.sleep(1)
        try:
            element = self.wd.find_element_by_class_name("ui-dialog-title")
            i = 0
            while True:
                if (element.text == "提示"):
                    print("检测到文章不一致>已自动更新到本章节")
                    element = self.wd.find_element_by_id("studyNow")
                    element.click()
                else:
                    i = i + 1
                if (i >= 4):
                    break
                time.sleep(1)
                return
        except NoSuchElementException as msg:
            print(u"查找元素异常>可无需理会 %s" % msg)
            return
        except Exception as Error:
            for line in Error:
                if (
                        line == """Message: no such element: Unable to locate element: {"method":"css selector","selector":".ui-dialog-title"}"""):
                    print("检测到文章不一致的错误提示>已跳过")
                    return
                else:
                    print("未知错误:", line)

    def get_completion_list(self, url):
        # 打开刷课地址
        self.wd.get(
            url
        )

        while True:  # 判断页面有没有加载成功
            if (self.wd.find_element_by_xpath("""//li[@class="kt-active"]""").text == "课件"):
                break

        time.sleep(3)

        self.open_class_tab()  # 展开列表
        time.sleep(3)
        self.class_list = []

        element1 = self.wd.find_elements_by_xpath(
            """//span[@class="sh-res-b " or @class="sh-res-b active"]""")  # 进度
        element2 = self.wd.find_elements_by_xpath(
            """//div[@class="sh-res-h am-margin-top-xs"]/a""")  # 标题
        element3 = self.wd.find_elements_by_xpath(
            """//div[@class="sh-res-h am-margin-top-xs"]/span/span""")  # 类型

        if (len(element1) != len(element2) or len(element1) != len(element3)):
            print("获取的参数有误！")
            print(len(element1), len(element2), len(element3))
        else:
            for i in range(len(element1)):
                dist = {}
                dist["id"] = i + 1
                dist["name"] = element2[i].text
                dist["type"] = element3[i].text
                dist["Completion"] = element1[i].get_attribute('title')
                dist["url"] = element2[i].get_attribute('data-href')
                self.class_list.append(dist)

    def run_guaji(self):  # 自动挂机菜单
        line_i = 0
        for line in self.class_list:
            line_i = line_i + 1
            print("当前", line_i, "/", len(self.class_list))
            if (line["type"] == "视频" and line["Completion"] != "100%"):
                print("载入视频:", line["name"], "完成度:", line["Completion"])
                self.wd.get("https://zjy2.icve.com.cn" + line["url"])
                self.is_Kejian_butong()  # 判断有没有提示
                self.wd.refresh()
                self.play_video()
                # print("视频:", element2[i].text, "播放完成")
                time.sleep(float("{:.1f}".format(random.uniform(30, 60))))
                print("延迟一段时间")
                os.system("cls")

            elif (line["type"] == "ppt" and line["Completion"] != "100%"):
                print("载入PPT:", line["name"], "完成度:", line["Completion"])
                self.wd.get("https://zjy2.icve.com.cn/" + line["url"])
                self.is_Kejian_butong()  # 判断有没有提示
                self.wd.refresh()
                self.play_ppt()
                time.sleep(float("{:.1f}".format(random.uniform(30, 60))))
                print("延迟一段时间")
                os.system("cls")

            elif (line["type"] == "压缩包" and line["Completion"] != "100%"):
                print("载入压缩包:", line["name"], "完成度:", line["Completion"])
                self.wd.get("https://zjy2.icve.com.cn/" + line["url"])
                self.is_Kejian_butong()  # 判断有没有提示
                time.sleep(float("{:.1f}".format(random.uniform(0, 10))))
                print("延迟一段时间")

            elif (line["type"] == "图片"  and line["Completion"] != "100%"):
                print("载入图片:", line["name"], "完成度:", line["Completion"])
                self.wd.get("https://zjy2.icve.com.cn/" + line["url"])
                self.is_Kejian_butong()  # 判断有没有提示
                time.sleep(float("{:.1f}".format(random.uniform(0, 10))))
                print("延迟一段时间")

            elif (line["type"] == "图文" and line["Completion"] != "100%"):
                print("载入图文:", line["name"], "完成度:", line["Completion"])
                self.wd.get("https://zjy2.icve.com.cn/" + line["url"])
                self.is_Kejian_butong()  # 判断有没有提示
                time.sleep(float("{:.1f}".format(random.uniform(0, 10))))
                print("延迟一段时间")

            elif (line["type"] == "链接" and line["Completion"] != "100%"):
                print("载入链接:", line["name"], "完成度:", line["Completion"])
                self.wd.get("https://zjy2.icve.com.cn/" + line["url"])
                self.is_Kejian_butong()  # 判断有没有提示
                time.sleep(float("{:.1f}".format(random.uniform(0, 10))))
                print("延迟一段时间")

            elif (line["type"] == "文档" and line["Completion"] != "100%"):
                print("载入文档:", line["name"], "完成度:", line["Completion"])
                self.wd.get("https://zjy2.icve.com.cn/" + line["url"])
                self.is_Kejian_butong()  # 判断有没有提示
                self.play_word()
                time.sleep(float("{:.1f}".format(random.uniform(0, 10))))
                print("延迟一段时间")

            elif (line["type"] == "文本" and line["Completion"] != "100%"):
                print("载入文本:", line["name"], "完成度:", line["Completion"])
                self.wd.get("https://zjy2.icve.com.cn/" + line["url"])
                self.is_Kejian_butong()  # 判断有没有提示
                self.play_word()
                time.sleep(float("{:.1f}".format(random.uniform(0, 10))))
                print("延迟一段时间")


            else:
                if (line["type"] == "压缩包"):
                    print("压缩包", line["name"], "已完成")
                elif (line["type"] == "图片"):
                    print("图片:", line["name"], "已完成")
                elif (line["type"] == "图文"):
                    print("图文:", line["name"], "已完成")
                elif (line["type"] == "链接"):
                    print("链接:", line["name"], "已完成")
                elif (line["type"] == "视频"):
                    print("视频:", line["name"], "已完成")
                elif (line["type"] == "ppt"):
                    print("PPT:", line["name"], "已完成")
                elif (line["type"] == "文档"):
                    print("文档:", line["name"], "已完成")
                elif (line["type"] == "文本"):
                    print("文本:", line["name"], "已完成")
                else:
                    print("未知的章节格式:",line["name"])

        print("本课程已全部完成")
        self.get_course_list() # 更新课程列表


    def play_word(self):  # 播放word
        print("文档已加载")
        # 麻了 文档也俩格式 有一个和ppt一样
        while True:  # 取回源码
            time.sleep(3)
            page_source = self.wd.page_source
            if (page_source.find("swiper-button-next") != -1 or page_source.find("MPreview-arrowBottom") != -1):
                break

        if (page_source.find("MPreview-arrowBottom") != -1):
            while True:  # 等待页面加载
                try:
                    nextbtn = self.wd.find_element_by_class_name("MPreview-arrowBottom")
                    if (nextbtn.text == "下一页"):
                        print("取得文档下一页按钮成功")
                        break
                    else:
                        time.sleep(1)
                except Exception as E:
                    print("取得文档下一页按钮出错了！")
                    print(E)

            all_page = int(self.wd.find_element_by_xpath("""//span[@class="MPreview-pageCount"]/em""").text)
            while True:
                now_page = int(self.wd.find_element_by_xpath("""//input[@name="newlyPicNum"]""").get_attribute("value"))
                if (now_page >= all_page):
                    time.sleep(5)
                    break
                else:
                    nextbtn.click()

                time.sleep(float("{:.1f}".format(random.uniform(0, 1))))

        else:

            while True:  # 等待页面加载
                try:
                    nextbtn = self.wd.find_element_by_class_name("swiper-button-next")
                    if (nextbtn.get_attribute("aria-label") == "Next slide"):
                        print("取得文档下一页按钮成功")
                        break
                    else:
                        time.sleep(1)
                except Exception as E:
                    print("取得文档下一页按钮出错了！")
                    print(E)

            time.sleep(1)

            element = self.wd.find_element_by_xpath("""//div[@class="swiper-button-next"]""")
            print(nextbtn)

            while True:
                # 点击下一页
                if (element.get_attribute("class") == "swiper-button-next swiper-button-disabled"):
                    time.sleep(5)
                    break
                else:
                    nextbtn.click()

                time.sleep(float("{:.1f}".format(random.uniform(0, 1))))

    def play_ppt(self):  # 播放ppt
        print("PPT已加载")
        # 突然发现PPT有俩种形式 一种是 iframe嵌套 另一种直接就是js
        while True:  # 取回源码
            time.sleep(3)
            page_source = self.wd.page_source
            if (page_source.find("iframe") != -1 or page_source.find("arrowBottom") != -1):
                break

        if (page_source.find("iframe") == -1):
            # 没找到 就是js模式
            while True:  # 等待页面加载
                try:
                    nextbtn = self.wd.find_element_by_class_name("MPreview-arrowBottom")
                    if (nextbtn.text == "下一页"):
                        print("取得ppt下一页按钮成功")
                        break
                    else:
                        time.sleep(1)
                except Exception as E:
                    print("取得PPT下一页按钮出错了！")
                    print(E)

            all_page = int(self.wd.find_element_by_xpath("""//span[@class="MPreview-pageCount"]/em""").text)
            while True:
                now_page = int(self.wd.find_element_by_xpath("""//input[@name="newlyPicNum"]""").get_attribute("value"))
                if (now_page >= all_page):
                    time.sleep(10)
                    break
                else:
                    nextbtn.click()
                    time.sleep(float("{:.1f}".format(random.uniform(0, 1))))
                time.sleep(float("{:.1f}".format(random.uniform(0, 1))))

        else:

            while True:  # 等待页面加载
                try:
                    nextbtn = self.wd.find_element_by_class_name("stage-next-btn")  # 取得下一页按钮信息
                    if (nextbtn.text == "下一页"):
                        print("取得ppt下一页按钮成功")
                        break
                    else:
                        time.sleep(1)
                except Exception as E:
                    print("取得PPT下一页按钮出错了！")
                    print(E)
            # 这里取页数的方法和前面不大一样
            # iframe嵌套内页 > 跳到内页中 https://zjy2.icve.com.cn//common/directory/directory.html?courseOpenId=cg8dawmrd4nkdqvwrb5g&openClassId=cuz0anyspp9euq6lxe9rrw&cellId=virdagqrji1jgxucluvsw&flag=s
            self.wd.switch_to.frame(self.wd.find_element_by_tag_name("iframe"))
            element = self.wd.find_elements_by_class_name("SC")  # 取得ppt div
            # print(nextbtn)
            # pages_all = len(element)  # 取得ppt页数
            # nextbtn2 = wd.find_element_by_id("player")  # 取得下一页按钮信息
            while True:
                # 点击下一页 5次
                self.wd.switch_to.default_content()  # 跳回主页
                for i in range(5):
                    nextbtn.click()
                    time.sleep(float("{:.1f}".format(random.uniform(0, 1))))

                self.wd.switch_to.frame(self.wd.find_element_by_tag_name("iframe"))  # 跳回内嵌

                if (element[len(element) - 1].get_attribute('style').find("display: block") != -1):
                    for i in range(10):
                        self.wd.switch_to.default_content()  # 跳回主页
                        nextbtn.click()
                        time.sleep(float("{:.1f}".format(random.uniform(0, 1))))

                    # 点击这个位置似乎可以解决 ppt加载不完全的问题
                    # for i in range(5):
                    #     nextbtn3 = wd.find_element_by_id("contentHolder")
                    #     nextbtn3.click()
                    #     time.sleep(0.5)
                    time.sleep(10)

                    break

                # print("pages_all", pages_all)
                time.sleep(float("{:.1f}".format(random.uniform(0, 1))))
            return

    def check_course(self):  # 课程选择器
        while True:
            print("-" * 30)
            self.show_course_list()
            print("-" * 30)
            num = input("请输入你要挂机刷课的课程的序号(输入N退出):")
            try:
                if (num.lower() == "n"):
                    print("已退出")
                    self.wd.quit()
                    break
                elif (num == ""):
                    print("请输入你的选择")
                else:
                    url = self.kecheng_list[int(num) - 1]["url"]
                    self.get_completion_list(url)
                    print("开始挂机刷课")
                    self.run_guaji()

            except Exception as Error:
                print("输入有误")
                print(Error)
                print(traceback.print_exc())
            finally:
                pass
                # os.system("cls")

# print('[{name:<{len}}\tx'.format(name=name+']',len=22-len(name.encode('GBK'))+len(name)))
